package com.mini.mybatis.executor.parameter;

import com.mini.mybatis.mapping.BoundSql;
import com.mini.mybatis.mapping.MappedStatement;
import com.mini.mybatis.mapping.ParameterMapping;
import com.mini.mybatis.reflection.MetaObject;
import com.mini.mybatis.session.Configuration;
import com.mini.mybatis.type.TypeHandler;
import com.mini.mybatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * 默认参数处理器实现
 * 负责将参数对象的值绑定到PreparedStatement中
 */
public class DefaultParameterHandler implements ParameterHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(DefaultParameterHandler.class);
    
    private final TypeHandlerRegistry typeHandlerRegistry;
    private final MappedStatement mappedStatement;
    private final Object parameterObject;
    private final BoundSql boundSql;
    private final Configuration configuration;
    
    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        this.mappedStatement = mappedStatement;
        this.parameterObject = parameterObject;
        this.boundSql = boundSql;
        this.configuration = mappedStatement.getConfiguration();
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    }
    
    @Override
    public Object getParameterObject() {
        return parameterObject;
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public void setParameters(PreparedStatement ps) throws SQLException {
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if (parameterMappings != null) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                Object value;
                String propertyName = parameterMapping.getProperty();
                
                if (boundSql.hasAdditionalParameter(propertyName)) {
                    // 从额外参数中获取值
                    value = boundSql.getAdditionalParameter(propertyName);
                } else if (parameterObject == null) {
                    value = null;
                } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                    // 如果参数对象本身就是基本类型，直接使用
                    value = parameterObject;
                } else {
                    // 从复杂对象中获取属性值
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    value = metaObject.getValue(propertyName);
                }
                
                // 获取类型处理器并设置参数
                TypeHandler typeHandler = parameterMapping.getTypeHandler();
                if (typeHandler == null) {
                    Class<?> javaType = parameterMapping.getJavaType();
                    if (value == null && javaType == null) {
                        javaType = Object.class;
                    }
                    typeHandler = typeHandlerRegistry.getTypeHandler(javaType);
                }
                
                try {
                    typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
                } catch (Exception e) {
                    throw new SQLException("设置参数时出错。参数索引: " + (i + 1) + ", 参数值: " + value + 
                            ", 原因: " + e.getMessage(), e);
                }
            }
        }
    }
}